package com.atom.module.lib.opengles.shader

import android.graphics.Color
import android.opengl.GLES30
import androidx.annotation.ColorInt
import com.atom.module.lib.opengles.code.*
import com.atom.module.lib.opengles.draw.GlDrawable
import com.atom.module.lib.opengles.util.ShaderUtils

class GlSimpleProgram : GlProgram(DefaultVShader.create(), DefaultFShader.create()) {


    private var color: FloatArray = floatArrayOf(1F, 1F, 1F, 1F)

    fun setColor(@ColorInt color: Int) {
        this.color = floatArrayOf(
            Color.red(color) / 255F,
            Color.green(color) / 255F,
            Color.blue(color) / 255F,
            Color.alpha(color) / 255F
        )
    }

    override fun onPreDraw(drawable: GlDrawable, modelViewProjectionMatrix: FloatArray) {
        super.onPreDraw(drawable, modelViewProjectionMatrix)

        // Copy the modelViewProjectionMatrix over.
        DefaultVShader.uniform_mvp_matrix_name.glUniformMatrix4fv(
            this.handle,
            1,
            false,
            modelViewProjectionMatrix,
            0
        )
        ShaderUtils.checkGLError("glUniformMatrix4fv")

        // Copy the color vector in.
        DefaultFShader.uniform_color_name.glUniform4fv(this.handle, 1, color, 0)
        ShaderUtils.checkGLError("glUniform4fv")

        // Enable the "aPosition" vertex attribute.
        DefaultVShader.attribute_position_name.glEnableVertexAttribArray(this.handle)
        ShaderUtils.checkGLError("glEnableVertexAttribArray")

        // Connect vertexBuffer to "aPosition".
        DefaultVShader.attribute_position_name.glVertexAttribPointer(
            this.handle, drawable.coordsPerVertex,
            GLES30.GL_FLOAT, false, drawable.vertexStride, drawable.vertexArray
        )

        ShaderUtils.checkGLError("glVertexAttribPointer")
    }

    override fun onPostDraw(drawable: GlDrawable) {
        super.onPostDraw(drawable)
        DefaultVShader.attribute_position_name.glDisableVertexAttribArray(this.handle)
    }

}


object DefaultVShader : GlCode() {

    val uniform_mvp_matrix_name: GLUniformVariable =
        GLUniformVariable(GLClass.Mat4.create("uMVPMatrix"))
    val attribute_position_name: GLAttributeVariable =
        GLAttributeVariable(GLClass.Vec4.create("aPosition"))

    override fun create(): String {
        return """
                    $uniform_mvp_matrix_name;
                    $attribute_position_name;
                    void main() {
                        gl_Position = ${uniform_mvp_matrix_name.name()} * ${attribute_position_name.name()};
                        gl_PointSize = 10.0 ;
                    }
                    """.trimIndent()
    }
}

object DefaultFShader : GlCode() {

    val uniform_color_name: GLUniformVariable = GLUniformVariable(GLClass.Vec4.create("uColor"))

    override fun create(): String {
        return """
            precision mediump float;
            $uniform_color_name;
            void main() {
                gl_FragColor = ${uniform_color_name.name()};
            }
        """.trimIndent()
    }
}